package com.jacky.iot.service;

import com.influxdb.client.InfluxDBClient;
import com.jacky.iot.tasks.CpuUsageTask;
import com.jacky.iot.commons.TaskType;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.*;

@Component
public class ScheduledTaskManager {

    private final Logger Log = LoggerFactory.getLogger(ScheduledTaskManager.class);

    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
    private final Map<String, TaskWrapper> scheduledTasks = new ConcurrentHashMap<>();

    private final InfluxDBClient dbClient;

    public ScheduledTaskManager(InfluxDBClient influxDb) {
        this.dbClient = influxDb;
    }

    @PostConstruct
    public void executeOsCollectTask() {
        CpuUsageTask task = new CpuUsageTask(dbClient);
        TaskWrapper tw = new TaskWrapper()
                .setTask(task)
                .setTaskType(TaskType.OS_COLLECT)
                .setTaskId(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
        newScheduledTask(tw);
    }


    public void newScheduledTask(TaskWrapper tw) {
        Log.info("new schedule task:{},delayMs:{},interval:{},intervalTU:{}", tw.getTaskId(), tw.getTaskDelayMs(), tw.getInterval(), tw.getIntervalTU());
        ScheduledFuture<?> future = executor.scheduleAtFixedRate(tw.getTask(), tw.getTaskDelayMs(), tw.getInterval(), tw.getIntervalTU());
        tw.setFuture(future);
        scheduledTasks.put(tw.getTaskId(), tw);
    }

    public void updateTask(String taskId, TaskWrapper tw) {
        cancelTask(taskId);
        newScheduledTask(tw);
    }

    public void cancelTask(String taskId) {
        if (StringUtils.isBlank(taskId)) {
            if (Log.isDebugEnabled()) {
                Log.debug("taskId can not be null");
            }
            return;
        }
        TaskWrapper tw = scheduledTasks.remove(taskId);
        if (tw != null) {
            Future<?> future = tw.getFuture();
            if (future != null) {
                future.cancel(false);
            }
        }
    }


    public List<TaskWrapper> getTaskWrappersByTaskType(TaskType tt) {
        return scheduledTasks.values().stream().filter(tw -> tw.getTaskType().equals(tt)).toList();
    }

    @PreDestroy
    public void shutdown() {
        executor.shutdown();
    }

}
